package cn.net.xyan.blossom.kotlin

import java.io.PrintWriter
import java.io.StringWriter
import java.beans.Introspector
import java.lang.RuntimeException


/**
 * Created by zarra on 2017/7/7.
 */

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class NoArg

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class AllOpen


class StatusAndMessageError(val status:Int?,message:String?,prev:Throwable?): RuntimeException(message,prev){
    constructor(status:Int?,prev:Throwable):this(status,null,prev)
    constructor(prev:Throwable):this(null,null,prev)
    constructor(status:Int?,message:String?):this(status,message,null)
    constructor(status:Int?):this(status,null,null)
    constructor(message:String?):this(-1,message,null)
}

val Throwable.stackTraceMessage:String get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    printStackTrace(pw)
    return sw.toString()
}

@NoArg
data class ErrorRsp(val msg:String){

    constructor(e:StatusAndMessageError) : this(e.message?:"") {
        this.code = e.status
        val sw = StringWriter()
        val pw = PrintWriter(sw)
        e.printStackTrace(pw)
        this.traceStack = sw.toString()
    }

    var code:Int? = null
    var traceStack:String? = null

    fun toError():StatusAndMessageError{
        val error = StatusAndMessageError(code,msg)
        return error
    }

}

fun <T:Any> T.getProperty(propertyName:String):Any?{
    val beanInfo = Introspector.getBeanInfo(this.javaClass)
    val descriptors = beanInfo.propertyDescriptors
    return if (descriptors.none {
        it.name == propertyName
    }) {
        null
    } else descriptors.first {
        it.name == propertyName
    }?.readMethod?.invoke(this)
}



